﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using VIP.Extension;

namespace VIP {

    /// <summary>
    /// 音频任务类
    /// </summary>
    [Serializable]
    class AudioTaskClass
    {
        public string Id;
        //结束时间
        public float TaskTime;
        //音频播放完回收到对象池回调
        public UnityAction<string,bool> Callback;
        //音频播放完回调
        public UnityAction Complete;
        //自动销毁
        public bool AutoDestroy;
    }

    /// <summary>
    /// 挂在一个对象上即可
    /// </summary>
    public class VIPAudio : VIPMonoSingleton<VIPAudio>
    {

        public UnityAction<string> IdNotFoundCallback;

        /// <summary>
        /// 任务列表
        /// </summary>
        private List<AudioTaskClass> taskTimes = new List<AudioTaskClass>();

        /// <summary>
        /// 延时用的
        /// </summary>
        private void Update()
        {
            for (int i = 0; i < taskTimes.Count; i++)
            {
                AudioTaskClass atc = taskTimes[i];
                if (Time.realtimeSinceStartup < atc.TaskTime)
                {
                    continue;
                }
                else
                {
                    string id = atc.Id;
                    UnityAction<string,bool> callback = atc.Callback;
                    UnityAction complete = atc.Complete;
                    bool autoDestroy = atc.AutoDestroy;
                    if (callback.IsNotNull())
                    {
                        callback(id, autoDestroy);
                    }
                    if (complete.IsNotNull())
                    {
                        complete();
                    }
                    taskTimes.RemoveAt(i);
                    i--;
                }
            }
        }

        /// <summary>
        /// 播放声音
        /// </summary>
        /// <param name="clip"></param>
        /// <param name="autoDestroy"></param>
        /// <returns></returns>
        public string Play(AudioClip clip, bool autoDestroy = false)
        {
            return Play(clip, null, autoDestroy);
        }

        /// <summary>
        /// 播放声音
        /// </summary>
        /// <param name="clip"></param>
        /// <param name="complete"></param>
        /// <returns></returns>
        public string Play(AudioClip clip, UnityAction complete)
        {
            return Play(clip, complete, false);
        }

        /// <summary>
        /// 播放声音
        /// </summary>
        /// <param name="clip">音源</param>
        /// <param name="complete">回调</param>
        /// <returns>音频id</returns>
        public string Play(AudioClip clip, UnityAction complete, bool autoDestroy)
        {
            //遍历音频Id列表
            foreach (Transform findTf in transform)
            {
                GameObject findObj = findTf.gameObject;
                string id = findObj.name;
                if (!findObj.activeSelf)
                {
                    //设置为正在播放
                    findObj.SetActive(true);
                    Fun(callback, findObj, clip, id, complete, autoDestroy);
                    return id;
                }
            }
            //给AudioSource对象起名字
            string rid = VIPRandomUtil.GetString(5);
            //创建预制体
            GameObject createObj = new GameObject(rid);
            //添加音频组件
            createObj.AddComponent<AudioSource>();
            createObj.transform.SetParent(transform);
            createObj.name = rid;
            Fun(callback, createObj, clip, rid, complete, autoDestroy);
            return rid;
        }

        /// <summary>
        /// 根据Id播放
        /// </summary>
        /// <param name="id"></param>
        /// <param name="clip"></param>
        /// <param name="complete"></param>
        public void Play(string id, AudioClip clip, bool autoDestroy = false)
        {
            Play(id, clip, null, autoDestroy);
        }

        /// <summary>
        /// 根据Id播放
        /// </summary>
        /// <param name="id"></param>
        /// <param name="clip"></param>
        /// <param name="complete"></param>
        public void Play(string id, AudioClip clip, UnityAction complete)
        {
            Play(id, clip, complete, false);
        }

        /// <summary>
        /// 根据Id播放
        /// </summary>
        /// <param name="id"></param>
        /// <param name="clip"></param>
        public void Play(string id, AudioClip clip, UnityAction complete, bool autoDestroy)
        {
            GameObject findObj = gameObject.FindChildByName(id);
            if (findObj.IsNotNull())
            {
                if (!findObj.activeSelf)
                {
                    //设置为正在播放
                    findObj.SetActive(true);
                    Fun(callback, findObj, clip, id, complete, autoDestroy);
                }
                else
                {
                    Stop(id);
                    findObj.SetActive(true);
                    Fun(callback, findObj, clip, id, complete, autoDestroy);
                }
            }
            else
            {
                if (IdNotFoundCallback.IsNotNull())
                {
                    IdNotFoundCallback(id);
                }
            }
        }

        /// <summary>
        /// 停止音频
        /// </summary>
        /// <param name="id">音频id</param>
        public void Stop(string id)
        {
            gameObject.FindChildByName(id).SetActive(false);
            AudioTaskClass atc = taskTimes.Find((x) => id.Equals(x.Id));
            if (atc.IsNotNull())
            {
                taskTimes.Remove(atc);
            }
        }

        /// <summary>
        /// 遍历禁用所有的音频
        /// </summary>
        public void StopAll()
        {
            List<GameObject> goList = gameObject.GetChildren();
            foreach (GameObject findGo in goList)
            {
                if (findGo.activeSelf)
                {
                    Stop(findGo.name);
                }
            }
        }

        /// <summary>
        /// 封装一下
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="obj"></param>
        /// <param name="clip"></param>
        /// <param name="id"></param>
        /// <param name="complete"></param>
        private void Fun(UnityAction<string,bool> callback, GameObject obj, AudioClip clip, string id, UnityAction complete ,bool autoDestroy)
        {
            AudioSource audio = obj.GetComponent<AudioSource>();
            audio.playOnAwake = false;
            //3D音频
            //audio.spatialBlend = 1;
            audio.clip = clip;
            audio.Play();
            //添加一个定时任务
            AddTaskTime(callback, audio.clip.length, id, complete, autoDestroy);
        }

        /// <summary>
        /// 开始计时
        /// </summary>
        /// <param name="callback">完成回调（携带id）</param>
        /// <param name="delay">延时时长</param>
        /// <param name="id">id</param>
        /// <param name="complete">完成回调</param>
        private void AddTaskTime(UnityAction<string,bool> callback, float delay, string id, UnityAction complete, bool autoDestroy)
        {
            float taskTime = Time.realtimeSinceStartup + delay;
            AudioTaskClass atc = new AudioTaskClass();
            atc.Id = id;
            atc.Callback = callback;
            atc.TaskTime = taskTime;
            atc.Complete = complete;
            atc.AutoDestroy = autoDestroy;
            taskTimes.Add(atc);
        }

        /// <summary>
        /// 音频播放完成改变状态
        /// </summary>
        /// <param name="id"></param>
        private void callback(string id,bool autoDestroy)
        {
            GameObject go = gameObject.FindChildByName(id);
            if (go.IsNotNull())
            {
                if (autoDestroy)
                {
                    go.Destroy();
                }
                else {
                    go.Disable();
                }
            }
        }

        /// <summary>
        /// 获取所有的Id
        /// </summary>
        /// <returns></returns>
        public List<string> GetIds()
        {
            List<string> ids = new List<string>();
            List<GameObject> gos = gameObject.GetChildren();
            foreach (GameObject go in gos)
            {
                ids.Add(go.name);
            }
            return ids;
        }

        /// <summary>
        /// 获取当前正在播放的所有Id
        /// </summary>
        /// <returns></returns>
        public List<string> GetPlayingIds()
        {
            List<string> ids = new List<string>();
            foreach (AudioTaskClass vatc in taskTimes)
            {
                ids.Add(vatc.Id);
            }
            return ids;
        }

        /// <summary>
        /// 获取音频长度
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public float Length(string id)
        {
            GameObject go = gameObject.FindChildByName(id);
            AudioSource audioSource = go.GetComponent<AudioSource>();
            return audioSource.clip.length;
        }

        /// <summary>
        /// 获取音频进度
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public float Progress(string id)
        {
            return 0.0f;
        }

    }

}
